<template>
  <div class="video-player-container">
    <div :id="containerId" class="video-player" :style="{ width: playerWidth, height: playerHeight }">
      <video ref="videoRef" :src="src" :poster="poster" :autoplay="autoplay" :controls="controls" :loop="loop"
        :muted="muted" :width="width" :height="height" class="video-element" @loadstart="onLoadStart"
        @loadeddata="onLoadedData" @canplay="onCanPlay" @play="onPlay" @pause="onPause" @ended="onEnded"
        @error="onError" @timeupdate="onTimeUpdate" @volumechange="onVolumeChange">
        您的浏览器不支持视频播放
      </video>
    </div>

    <!-- 加载状态 -->
    <div v-if="loading" class="loading-overlay">
      <div class="loading-spinner"></div>
      <p>视频加载中...</p>
    </div>

    <!-- 错误状态 -->
    <div v-if="error" class="error-overlay">
      <div class="error-icon">⚠️</div>
      <p class="error-message">{{ error }}</p>
      <button @click="retry" class="retry-button">重试</button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted, watch } from 'vue'
import type { PlayerConfig } from '../types/vod'

interface Props {
  /** 播放地址 */
  src: string
  /** 封面图片 */
  poster?: string
  /** 是否自动播放 */
  autoplay?: boolean
  /** 是否显示控制条 */
  controls?: boolean
  /** 播放器宽度 */
  width?: string | number
  /** 播放器高度 */
  height?: string | number
  /** 是否循环播放 */
  loop?: boolean
  /** 是否静音 */
  muted?: boolean
  /** 容器ID前缀 */
  containerIdPrefix?: string
}

interface Emits {
  /** 播放开始 */
  play: []
  /** 播放暂停 */
  pause: []
  /** 播放结束 */
  ended: []
  /** 播放错误 */
  error: [error: string]
  /** 时间更新 */
  timeUpdate: [currentTime: number, duration: number]
  /** 音量变化 */
  volumeChange: [volume: number]
  /** 视频加载完成 */
  loaded: []
}

const props = withDefaults(defineProps<Props>(), {
  autoplay: false,
  controls: true,
  loop: false,
  muted: false,
  containerIdPrefix: 'video-player'
})

const emit = defineEmits<Emits>()

// 响应式数据
const videoRef = ref<HTMLVideoElement>()
const loading = ref(false)
const error = ref('')
const containerId = ref(`${props.containerIdPrefix}-${Date.now()}`)

// 计算属性
const playerWidth = computed(() => {
  if (typeof props.width === 'number') return `${props.width}px`
  return props.width || '100%'
})

const playerHeight = computed(() => {
  if (typeof props.height === 'number') return `${props.height}px`
  return props.height || 'auto'
})

// 事件处理
const onLoadStart = () => {
  loading.value = true
  error.value = ''
}

const onLoadedData = () => {
  loading.value = false
  emit('loaded')
}

const onCanPlay = () => {
  loading.value = false
}

const onPlay = () => {
  emit('play')
}

const onPause = () => {
  emit('pause')
}

const onEnded = () => {
  emit('ended')
}

const onError = (event: Event) => {
  loading.value = false
  const target = event.target as HTMLVideoElement
  const errorMessage = target.error?.message || '视频播放出错'
  error.value = errorMessage
  emit('error', errorMessage)
}

const onTimeUpdate = () => {
  if (videoRef.value) {
    const currentTime = videoRef.value.currentTime
    const duration = videoRef.value.duration || 0
    emit('timeUpdate', currentTime, duration)
  }
}

const onVolumeChange = () => {
  if (videoRef.value) {
    emit('volumeChange', videoRef.value.volume)
  }
}

// 重试播放
const retry = () => {
  error.value = ''
  if (videoRef.value) {
    videoRef.value.load()
  }
}

// 播放控制方法
const play = () => {
  return videoRef.value?.play()
}

const pause = () => {
  videoRef.value?.pause()
}

const setCurrentTime = (time: number) => {
  if (videoRef.value) {
    videoRef.value.currentTime = time
  }
}

const setVolume = (volume: number) => {
  if (videoRef.value) {
    videoRef.value.volume = Math.max(0, Math.min(1, volume))
  }
}

const getCurrentTime = () => {
  return videoRef.value?.currentTime || 0
}

const getDuration = () => {
  return videoRef.value?.duration || 0
}

const getVolume = () => {
  return videoRef.value?.volume || 0
}

const isPaused = () => {
  return videoRef.value?.paused ?? true
}

// 监听src变化
watch(() => props.src, (newSrc) => {
  if (newSrc && videoRef.value) {
    error.value = ''
    videoRef.value.load()
  }
})

// 暴露方法给父组件
defineExpose({
  play,
  pause,
  setCurrentTime,
  setVolume,
  getCurrentTime,
  getDuration,
  getVolume,
  isPaused,
  retry
})
</script>

<style scoped>
.video-player-container {
  position: relative;
  display: inline-block;
  width: 100%;
}

.video-player {
  position: relative;
  background: #000;
  border-radius: 8px;
  overflow: hidden;
}

.video-element {
  width: 100%;
  height: 100%;
  display: block;
}

.loading-overlay,
.error-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.8);
  color: white;
  border-radius: 8px;
}

.loading-spinner {
  width: 40px;
  height: 40px;
  border: 4px solid rgba(255, 255, 255, 0.3);
  border-top: 4px solid #fff;
  border-radius: 50%;
  animation: spin 1s linear infinite;
  margin-bottom: 16px;
}

@keyframes spin {
  0% {
    transform: rotate(0deg);
  }

  100% {
    transform: rotate(360deg);
  }
}

.error-overlay {
  text-align: center;
}

.error-icon {
  font-size: 48px;
  margin-bottom: 16px;
}

.error-message {
  margin: 0 0 16px 0;
  font-size: 16px;
}

.retry-button {
  padding: 8px 16px;
  background: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  transition: background-color 0.2s;
}

.retry-button:hover {
  background: #0056b3;
}
</style>
